﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using EHR.Elements;

namespace EHR.Ctrls
{
    public partial class FrictionPanel : UserControl
    {
        public event EventHandler Reset;
        private double _zoomRate = 1;
        private bool _friction = true;
        private bool _isDragging = false;
        private Point _mouseDownPoint;
        private Point _prevPoint;
        private Point _currPoint;
        private Point _mouseDownContentPosition;
        private Point _moveTo;

        public double ZoomRate 
        { 
            get { return _zoomRate; } 
            set 
            {
                _zoomRate = value;
                daScaleX.To = _zoomRate;
                daScaleY.To = _zoomRate;
                sbScaleContent.Begin();
            } 
        }

        public Size ContentSize { get; set; }
        
        public FrictionPanel()
        {
            InitializeComponent();
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);

        }

        public UIElement Content
        {
            get
            {
                if (contentGrid.Children.Count == 0)
                {
                    return null;
                }
                return contentGrid.Children[0]; 
            }
            set
            {
                contentGrid.Children.Clear();
                contentGrid.Children.Add(value);
            }
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            if (!_friction)
            {
                return;
            }

            double x = xTranslate.X;
            double y = xTranslate.Y;
            double w = _moveTo.X - x;
            double h = _moveTo.Y - y;
            if (Math.Abs(w * ZoomRate) > 1)
            {
                double step = w / 10;
                xTranslate.X = x + step;
            }
            if (Math.Abs(h * ZoomRate) > 1)
            {
                double step = h / 10;
                xTranslate.Y = y + step;
            }
        }

        private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!_friction)
            {
                return;
            }

            _isDragging = true;

            _mouseDownPoint = e.GetPosition(bgGrid);
            _currPoint = _mouseDownPoint;
            _prevPoint = _mouseDownPoint;
            _mouseDownContentPosition = new Point(xTranslate.X, xTranslate.Y);
            LayoutRoot.CaptureMouse();
        }

        private void LayoutRoot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _isDragging = false;
            LayoutRoot.ReleaseMouseCapture();
        }

        private void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
        {
            if (!_isDragging)
            {
                return ;
            }
            _prevPoint = _currPoint;
            _currPoint = e.GetPosition(bgGrid);
            double w = _currPoint.X - _mouseDownPoint.X;
            double h = _currPoint.Y - _mouseDownPoint.Y;
            _moveTo.X = _mouseDownContentPosition.X + w;
            _moveTo.Y = _mouseDownContentPosition.Y + h;
        }

        private void LayoutRoot_LostMouseCapture(object sender, MouseEventArgs e)
        {
            _isDragging = false;
        }

        public void MoveTo(Point to, TimeSpan duration)
        {
            _friction = false;
            daMoveLeft.Duration = new Duration(duration);
            daMoveTop.Duration = new Duration(duration);
            _moveTo.X = to.X;
            _moveTo.Y = to.Y;
            sbMoveTo.Begin();
        }

        public Point Position
        {
            get { return _moveTo; }
        }

        private void sb_Completed(object sender, EventArgs e)
        {
            _friction = true;
        }

        private void LayoutRoot_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (e.Delta > 0)
            {
                if (ZoomRate >= 10)
                {
                    return;
                }
                ZoomRate = ZoomRate * 1.25;
            }
            else
            {
                if (ZoomRate <= 0.1)
                {
                    return;
                }
                ZoomRate = ZoomRate * 0.8;
            }
        }
        
        private void navigater_Navigating(object sender, Elements.NavigateEventArgs e)
        {
            double margin = 20 / ZoomRate;
            double gw = LayoutRoot.ActualWidth / 2 / ZoomRate;
            double gh = LayoutRoot.ActualHeight / 2 / ZoomRate;
            switch (e.Mode)
            {
                case MapNavigateMode.Reset:
                    //MoveTo(new Point(0, 0), TimeSpan.FromSeconds(0.4));
                    _moveTo.X = 0;
                    _moveTo.Y = 0;
                    ZoomRate = 1;
                    OnReset();
                    break;
                case MapNavigateMode.ToLeft:
                    _moveTo.X = ContentSize.Width / 2 - gw + margin;
                    break;
                case MapNavigateMode.ToRight:
                    _moveTo.X = -ContentSize.Width / 2 + gw - margin;
                    break;
                case MapNavigateMode.ToTop:
                    _moveTo.Y = ContentSize.Height / 2 - gh + margin;
                    break;
                case MapNavigateMode.ToBottom:
                    _moveTo.Y = -ContentSize.Height / 2 + gh - margin;
                    break;
                default:
                    break;
            }
        }

        private void OnReset()
        {
            if (Reset != null)
            {
                Reset(this, new EventArgs());
            }
        }
    }
}
